#include "stdafx.h"
//-------------------------------------------------------------------------------------------------
//ImageExpt.cpp  - Image Experiment       
//-------------------------------------------------------------------------------------------------
//FreeBSD License
//Copyright 2012 Will Stott All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification, are
//permitted provided that the following conditions are met:
//
//   1. Redistributions of source code must retain the above copyright notice, this list of
//      conditions and the following disclaimer.
//
//   2. Redistributions in binary form must reproduce the above copyright notice, this list
//      of conditions and the following disclaimer in the documentation and/or other materials
//      provided with the distribution.
//
//THIS SOFTWARE IS PROVIDED BY Will Stott ``AS IS'' AND ANY EXPRESS OR IMPLIED
//WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Will Stott OR
//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
//ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//The views and conclusions contained in the software and documentation are those of the
//authors and should not be interpreted as representing official policies, either expressed
//or implied, of Will Stott.
//
//----Authors--------------------------------------------------------------------------------------
//created by: will.stott@ucl.ac.uk Feb 2012
//
//----Comments-------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------

#include "ImageExpt.h"
#include "ImageProcessFile.h"
#include "ImageProcStep.h"
#include "ImageProcSteps.h"

const char * const ImageExpt::Invalid = "Invalid";
const char * const ImageExpt::IefRefPrefix = "IEFRef-";
const char * const ImageExpt::Editor = "ImageCurator ";
const char * const ImageExpt::NotFound = "(not found)";
const char * const ImageExpt::DateTimeFrmStr = "%d-%m-%y.%H:%M:%S";		//match with DateTimeFrmStrLen, ImageProcessFile::DateTimeFrmStr and ImageDataset::DateTimeFrmStr

const char * const ImageExpt::xmlHeaderInfo = "Info";			//same as ImageDataset::xmlHeaderInfo
const char * const ImageExpt::xmlHeaderInfoIDFRef = "IDFRef";		//same as ImageDataset::xmlHeaderIDFRef	
const char * const ImageExpt::xmlHeaderInfoIEFRef = "IEFRef";
const char * const ImageExpt::xmlHeaderInfoOwner = "IEFOwner";
const char * const ImageExpt::xmlHeaderInfoCreateDate = "IEFCreateDate";
const char * const ImageExpt::xmlHeaderInfoEditor = "IEFEditor";
const char * const ImageExpt::xmlHeaderInfoIEFDescription = "IEFDesc";
const char * const ImageExpt::xmlHeaderInfoIEFVersion = "IEFVer";


ImageExpt::~ImageExpt(void)
{
	if ( _pDoc != '\0')
		delete _pDoc; 
	if ( _pStrFilePathNameBuffer != '\0' )
		free(_pStrFilePathNameBuffer);
}


void ImageExpt::DeleteMe()
{
	delete this;
}

ImageExpt *ImageExpt::CreateImageExpt(const wchar_t *PathFileNameIEFwStr, const wchar_t *PathFileNameTemplateIEFwStr, const wchar_t *IefOwner, const wchar_t *Description, ImageExpt::CreateMode mode)
{
	ImageExpt *rc = '\0';

	if ((PathFileNameIEFwStr == '\0') || (IefOwner == '\0') || (Description == '\0') )
		ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "param PathFileNameIEFwStr or IefOwner or Description is null" );
	else
	{
		if ((rc = new ImageExpt()) == '\0')
			ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "unable to create ImageExpt()" );
		else
		{
			bool ok = false;

			const char *owner = ImageExptLib::ConvertwStrToStr(rc->_pStrFilePathNameBuffer, ImageExptLib::MaxPathFileNameLen, IefOwner, ImageExptLib::MaxPathFileNameLen);
			if ( owner == '\0' )
				ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "ImageExptLib::ConvertwStrToStr() failed to convert param IefOwner" );	
			else
			{
				rc->_Owner = owner;
				const char *desc = ImageExptLib::ConvertwStrToStr(rc->_pStrFilePathNameBuffer, ImageExptLib::MaxPathFileNameLen, Description, ImageExptLib::MaxPathFileNameLen);
				if ( desc == '\0' )
					ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "ImageExptLib::ConvertwStrToStr() failed to convert param Description" );	
				else
				{
					rc->_Description = desc; 
					const char *pathfilenameIefStr = ImageExptLib::ConvertwStrToStr(rc->_pStrFilePathNameBuffer, ImageExptLib::MaxPathFileNameLen, PathFileNameIEFwStr, ImageExptLib::MaxPathFileNameLen);
					if ( pathfilenameIefStr == '\0' )
						ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "ImageExptLib::ConvertwStrToStr() failed to convert param PathFileNameIEF" );	
					else
					{
						rc->_IEFPathFileName = pathfilenameIefStr;
						if (mode == ImageExpt::FromFile )
						{			//create from file
							if ((rc->_pDoc = new TiXmlDocument()) != '\0')
							{
								if ( rc->_pDoc->LoadFile(rc->_IEFPathFileName.c_str()) == false) 
									ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "failed to open %s", rc->_IEFPathFileName.c_str() );	
								else
								{
									if ((rc->_pHeader = TinyXmlHelper::GetHeaderElement(rc->_pDoc)) == '\0')
										ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "failed to create header" );

									if ((rc->_pHeaderProcSteps = TinyXmlHelper::FindChildXmlElement(rc->_pHeader, ImageProcSteps::xmlProcSteps)) == '\0')
										rc->_pHeaderProcSteps = TinyXmlLib::CreateSection( rc->_pHeaderProcSteps, ImageProcSteps::xmlProcSteps, "Image Processing Steps" );  //new TiXmlElement( ImageProcSteps::xmlProcSteps ); //

									if ((rc->_pBody= TinyXmlHelper::GetBodyElement(rc->_pDoc)) == '\0')
										ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "failed to create body" );
									if ((rc->_pBodyImages = TinyXmlHelper::FindChildXmlElement(rc->_pBody, ImageProcessFile::xmlImages)) == '\0')
										ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "failed to create images in body" );

									if ((rc->_pHeader != '\0') && (rc->_pBody != '\0') && (rc->_pBodyImages != '\0') && (rc->_pHeaderProcSteps != '\0'))
									{
										rc->SetIdentity();
										std::string editor(ImageExpt::Editor);
										editor += ImageExptLib::GetLibVersion();
										if ( rc->SetHeaderInfo(editor.c_str(), "1") == true)
											ok = true;
									}
								}
							}
						}
						else
						{
							if ((rc->_pDoc = new TiXmlDocument(rc->_IEFPathFileName.c_str())) != '\0')
							{						//create from defaults
								TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "yes" );
								rc->_pDoc->LinkEndChild( decl );

								TiXmlComment * doctitle = new TiXmlComment( "Image workflow engine v0.0 - image experiment file" );
								rc->_pDoc->LinkEndChild( doctitle );

								TiXmlElement * content = new TiXmlElement( TinyXmlHelper::xmlDocName );
								rc->_pDoc->LinkEndChild( content );

								TiXmlDocument *pDocTemplate = '\0';
								TiXmlElement * templateHdrContent = '\0';
								TiXmlElement * templateBodyContent = '\0';

								if ((PathFileNameTemplateIEFwStr != '\0') && (mode == ImageExpt::FromTempate))
								{					//create rest from template
									if ((pDocTemplate = new TiXmlDocument()) == '\0')
										ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "failed to create pDocTempate" );	
									else
									{
										const char *pathfilenameTemplateIefStr  = ImageExptLib::ConvertwStrToStr(rc->_pStrFilePathNameBuffer, ImageExptLib::MaxPathFileNameLen, PathFileNameTemplateIEFwStr, ImageExptLib::MaxPathFileNameLen);
										if ( pathfilenameTemplateIefStr == '\0' )
											ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "ImageExptLib::ConvertwStrToStr() failed to convert param TemplateIEF" );	
										else
										{
											std::string templateFilename(pathfilenameTemplateIefStr);
											if ( pDocTemplate->LoadFile(templateFilename.c_str()) == false) 
												ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "failed to open template %s", templateFilename.c_str() );
											else
											{
												templateHdrContent = TinyXmlHelper::GetHeaderElement(pDocTemplate);
												templateBodyContent = TinyXmlHelper::GetBodyElement(pDocTemplate);
											}
										}
									}
								}
								if ((ok = rc->CreateHeader(content, templateHdrContent)) == false)
									ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "failed to create header contents" );
								else
								{
									if (rc->CreateBody(content, templateBodyContent) ==  false)
										ImageExptLib::LogMsg("ImageExpt::CreateImageExpt", "failed to create body contents" );
									else
									{
										rc->SetIdentity();
										std::string editor(ImageExpt::Editor);
										editor += ImageExptLib::GetLibVersion();
										if ( rc->SetHeaderInfo(editor.c_str(), "1") == true)
											ok = true;
									}
								}
								if (pDocTemplate != '\0')
									delete pDocTemplate;
							}
						}
					}
				}
			}
			if ((ok == false) || (rc->SaveFile() == false))
			{
				delete rc;
				rc = '\0';
			}
		}
	}
	return rc;
}

bool ImageExpt::SaveFile() 
{ 	
	bool rc = false;

	if (_pDoc == '\0')
		ImageExptLib::LogMsg("ImageExpt::SaveFile", "_pDoc is null" );
	else
	{
		if ( _pDoc->SaveFile() == true)
			rc = true;
	}
	return rc;
}

//-------------------------------------------------------------------------------------------------
//			P R I V A T E
//-------------------------------------------------------------------------------------------------


ImageExpt::ImageExpt(void) :
	  _IefRef(ImageExpt::Invalid),
	   _Owner(ImageExpt::Invalid),
	   _CreateDate(ImageExpt::Invalid),
	   _Description(ImageExpt::Invalid),
	  _pDoc('\0'),
	  _pHeader('\0'),
	  _pHeaderProcSteps('\0'),
	  _pBody('\0'),
	  _pBodyImages('\0'),
	  _pStrFilePathNameBuffer('\0')
{
	 _pStrFilePathNameBuffer = (char *) malloc( (ImageExptLib::MaxPathFileNameLen+1) * sizeof(char));

}

bool ImageExpt::CreateHeader(TiXmlElement * content, TiXmlElement * templateHdrContent)
{
	bool rc = false;

	if (content == '\0')
		ImageExptLib::LogMsg("ImageExpt::CreateHeader()", "Error: content param is null");
	else
	{
		if ( templateHdrContent != '\0')
		{
			if((_pHeader = TinyXmlHelper::DeepCopyXmlElement(templateHdrContent)) == '\0')
				ImageExptLib::LogMsg("ImageExpt::CreateHeader()", "Error: TinyXmlHelper::DeepCopyXmlElement(templateHdrContent) failed");
			else
			{
				//_pHeaderProcSteps = new TiXmlElement( ImageProcSteps::xmlProcSteps );// 
	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  this causes TinyXml to hang during ief->SaveFile(), though before doing so you need to call if ( steps->SaveToXml(pStepsXml) == false) in CArchiveProcGUIDoc::CreateImageExptFile
				//if ((_pHeaderProcSteps = TinyXmlHelper::FindChildXmlElement(_pHeader, ImageProcSteps::xmlProcSteps)) == '\0')
				//	_pHeaderProcSteps = TinyXmlLib::CreateSection( _pHeader, ImageProcSteps::xmlProcSteps, "Image Processing Steps" );		
				//if ( _pHeaderProcSteps != '\0')
				//{
				//	if (content->LinkEndChild(_pHeader ) != '\0') 
				//		rc = true;
				//}
	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
				if ((_pHeaderProcSteps = TinyXmlHelper::FindChildXmlElement(_pHeader, ImageProcSteps::xmlProcSteps)) == '\0')
					_pHeaderProcSteps = TinyXmlLib::CreateSection( _pHeader, ImageProcSteps::xmlProcSteps, "Image Processing Steps" );
				if (_pHeaderProcSteps == '\0')
					ImageExptLib::LogMsg("ImageExpt::CreateHeader()", "Error: _pHeaderProcSteps is null");
				else
					rc = true;
			}
		}
		else
		{
			if((_pHeader = new TiXmlElement( TinyXmlHelper::xmlHeaderElementName )) == '\0')
				ImageExptLib::LogMsg("ImageExpt::CreateHeader()", "Error: _pHeader = new TiXmlElement( TinyXmlHelper::xmlHeaderElementName ) is null");
			else
			{
				//TiXmlElement *whatever = new TiXmlElement( ImageProcessFile::whatever );
				//if (whatever != '\0')
				//{
				//	if (_pHeader->LinkEndChild( whatever ) != '\0')
				//		rc = true;	//must only be in last block, remove rc = true from previous block
				//	else
				//	{
				//		delete whatever;
				//		whatever = '\0';
				//	}
				//}
				_pHeaderProcSteps = new TiXmlElement( ImageProcSteps::xmlProcSteps );
				if (_pHeaderProcSteps == '\0')
					ImageExptLib::LogMsg("ImageExpt::CreateHeader()", "Error: _pHeaderProcSteps = new TiXmlElement( ImageProcSteps::xmlProcSteps ) is null");
				else
				{
					if (_pHeader->LinkEndChild( _pHeaderProcSteps ) == '\0')
					{
						ImageExptLib::LogMsg("ImageExpt::CreateHeader()", "Error: _pHeader->LinkEndChild( _pHeaderProcSteps ) is null");
						delete _pHeaderProcSteps;
						_pHeaderProcSteps = '\0';
					}
				}
				if (_pHeaderProcSteps != '\0' )
				{
					TiXmlElement *pAnalysisStep = new TiXmlElement( ImageProcStep::xmlProcStep );
					if (pAnalysisStep == '\0')
						ImageExptLib::LogMsg("ImageExpt::CreateHeader()", "Error: pAnalysisStep = new TiXmlElement( ImageProcStep::xmlProcStep ) is null");
					else
					{
						pAnalysisStep->SetAttribute(ImageProcStep::attribStepAnalysis, ImageProcStep::attribStepAnalysisYes);
						if (_pHeaderProcSteps->LinkEndChild( pAnalysisStep ) != '\0')
							rc = true;	//must only be in last block, remove rc = true from previous block
						else
						{
							ImageExptLib::LogMsg("ImageExpt::CreateHeader()", "Error: _pHeaderProcSteps->LinkEndChild( pAnalysisStep ) is null");
							delete pAnalysisStep;
							pAnalysisStep = '\0';
						}
					}
				}
			}
		}
		if ( rc == true )
		{
			if (content->LinkEndChild( _pHeader ) == '\0')
			{
				ImageExptLib::LogMsg("ImageExpt::CreateHeader()", "Error: content->LinkEndChild( _pHeader ) is null");
				rc = false;
			}
		}
		if ( rc == false )
		{
			if ( _pHeaderProcSteps != '\0')
				delete _pHeaderProcSteps;
			_pHeaderProcSteps = '\0';
			if (_pHeader != '\0')
				delete _pHeader;	//will delete any elements successfully added above
			_pHeader = '\0';
		}
	}
	return rc;
}

bool ImageExpt::CreateBody(TiXmlElement * content, TiXmlElement * templateBodyContent)
{
	bool rc = false;

	if (templateBodyContent != '\0')
	{
		if((_pBody = TinyXmlHelper::DeepCopyXmlElement(templateBodyContent)) != '\0')
		{
			if (content->LinkEndChild( _pBody ) != '\0') 
			{
				if ((_pBodyImages = TinyXmlHelper::FindChildXmlElement(_pBody, ImageProcessFile::xmlImages)) != '\0')
					rc = true;
			}
		}
	}
	else
	{
		if((_pBody = new TiXmlElement( TinyXmlHelper::xmlBodyElementName )) != '\0')
		{
			_pBodyImages = new TiXmlElement( ImageProcessFile::xmlImages );
			if (_pBodyImages != '\0')
			{
				if (_pBody->LinkEndChild(_pBodyImages) != '\0')
					rc = true;
				else
				{
					delete _pBodyImages;
					_pBodyImages = '\0';
				}
			}
			//todo - create other default elements here
			//TiXmlElement *whatever = new TiXmlElement( ImageProcessFile::whatever );
			//if (whatever != '\0')
			//{
			//	if (_pBody->LinkEndChild( whatever ) != '\0')
			//		rc = true;		//must only be in last block, remove rc = true from previous block
			//	else
			//	{
			//		delete whatever;
			//		whatever = '\0';
			//	}
			//}
			if ( rc == true )
			{
				if (content->LinkEndChild( _pBody ) == '\0') 
					rc = false;
			}
		}
		if ( rc == false )
		{
			delete _pBody;	//will delete any elements successfully added above
			_pBody = '\0';
			_pBodyImages = '\0';
		}
	}
	return rc;
}


bool ImageExpt::SetHeaderInfo(const char *editor, const char *version)
{
	bool rc = false;

//    <Info Owner="will.stott@ucl.ac.uk" CreateDate="22-07-2012 13:03:16" IEFRef="IEFRef-will.stott@ucl.ac.uk-22-07-2012.13:03:16" IEFEditor="ImageCurator v1.0.0.6" Description="Bulky Ovaries Studies - Pilot - Prof Campbell" Version="1">IDF Header</Info>

	if ((editor == '\0') || (version == '\0'))
		ImageExptLib::LogMsg("ImageExpt::SetHeaderInfo()", "editor or version params are null" );
	else
	{
		if ((_Owner == ImageExpt::Invalid) || (_CreateDate == ImageExpt::Invalid ) || (_IefRef == ImageExpt::Invalid) || (_Description == ImageExpt::Invalid))
			ImageExptLib::LogMsg("ImageExpt::SetHeaderInfo()", "_Owner, _CreateDate, _IefRef or _Description are not set" );
		else
		{
			TiXmlElement  *header = '\0';
			if ( (header = GetHeader()) == '\0')
				ImageExptLib::LogMsg("ImageExpt::SetHeaderInfo()", "root header element not found" );
			else
			{
				std::string IdfRef(ImageExpt::NotFound);
				TiXmlElement  *info = '\0';
				if ( (info = TinyXmlHelper::FindChildXmlElement(header, ImageExpt::xmlHeaderInfo)) != '\0')
				{
					IdfRef = info->Attribute(ImageExpt::xmlHeaderInfoIDFRef);
					header->RemoveChild(info);
					info = '\0';
				}

				if ((info = new TiXmlElement( ImageExpt::xmlHeaderInfo )) != '\0')
				{
					if ( header->LinkEndChild( info ) == '\0')
						delete info;
					else
					{
						info->SetAttribute(ImageExpt::xmlHeaderInfoIEFRef, _IefRef.c_str());
						info->SetAttribute(ImageExpt::xmlHeaderInfoOwner, _Owner.c_str());
						info->SetAttribute(ImageExpt::xmlHeaderInfoCreateDate, _CreateDate.c_str());
						info->SetAttribute(ImageExpt::xmlHeaderInfoEditor, editor);
						info->SetAttribute(ImageExpt::xmlHeaderInfoIEFDescription, _Description.c_str());
						info->SetAttribute(ImageExpt::xmlHeaderInfoIEFVersion, version);
						info->SetAttribute(ImageExpt::xmlHeaderInfoIDFRef, IdfRef.c_str());
						rc = true;
					}
				}
			}
		}
	}
	return rc;
}

void ImageExpt::SetIdentity()		
{
    char       buff[80]; 
    time_t t = time(0);   // get time now 
    struct tm * now = localtime( & t ); 
	strftime(buff, sizeof(buff), ImageExpt::DateTimeFrmStr, now); 
	_CreateDate = buff;

	_IefRef = ImageExpt::IefRefPrefix;
	_IefRef += _Owner;
	_IefRef += "-";
	_IefRef += buff;
}


//-------------------------------------------------------------------------------------------------
//			E N D   O F   F I L E
//-------------------------------------------------------------------------------------------------
